package com.lh.serverforwebrtc.websocket.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lh.serverforwebrtc.bean.UserBean;
import com.lh.serverforwebrtc.bean.UserStatusBean;
import com.lh.serverforwebrtc.service.RoomService;
import com.lh.serverforwebrtc.service.UserService;
import com.lh.serverforwebrtc.service.UserStatusService;
import com.lh.serverforwebrtc.websocket.message.MsgHandler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: Lh
 * @Description:
 * @Date: Created in 7:48 2022/6/10
 */
@Slf4j
@Component
@ServerEndpoint(value = "/websocketserve/{id}")
public class WebSocketServer {

    /**
     * 与某个客户端的连接对话，需要通过它来给客户端发送消息
     */
    private Session session;

    @Autowired
    private RoomService roomService;

    @Autowired
    private UserStatusService statusService;

    @Autowired
    private UserService userService;

    /**
     * 用来存储所有连接服务的客户端
     */
    private static ConcurrentHashMap<String,WebSocketServer> webSocketSet = new ConcurrentHashMap<>();

    private static WebSocketServer webSocket;

    private MsgHandler msgHandler;

    @PostConstruct
    public void init(){
        webSocket = this;
        msgHandler = new MsgHandler(webSocket);
    }

    /**
     * 客户端连接监听
     * @param session 客户端连接会话
     * @param id 客户端id
     */
    @OnOpen
    public void OnOpen(Session session,@PathParam("id")String id){
        log.info("用户上线---->{}",id);
        this.session = session;
        if(webSocketSet.containsKey(id)){
            webSocketSet.remove(id);
            webSocketSet.put(id,this);
        }else{
            System.out.println("id:"+id);
            webSocketSet.put(id,this);
        }
        //通过ID查询user 的用户名   user_id=37
        UserBean user = webSocket.userService.getUserById(Long.valueOf(id));
        webSocket.statusService.addOnlineUser(new UserStatusBean(Integer.valueOf(id),user.getUserName()));
        onLineMessage();
    }

    private void onLineMessage(){
        try {
            JSONObject jsonObject = new JSONObject();
            List<UserStatusBean> onLineUser = webSocket.statusService.getOnLineUser();
            jsonObject.put("action","user_online");
            jsonObject.put("data",JSON.toJSONString(onLineUser));
            for (String idKey : webSocketSet.keySet()){
                webSocketSet.get(idKey).session.getBasicRemote().sendText(JSON.toJSONString(jsonObject));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 客户端连接关闭监听
     * @param id 客户端id
     */
    @OnClose
    public void OnClose(@PathParam("id")String id){
        log.info("用户离线:{}",id);
        webSocketSet.remove(id);
        webSocket.statusService.removeOnlineUser(Integer.valueOf(id));
        onLineMessage();
    }

    /**
     * 连接异常监听
     */
    @OnError
    public void onError(Session session, Throwable error,@PathParam("id")String id) {
        log.info("[WebSocket] 错误:{}",error.getMessage()+id);
        webSocket.statusService.removeOnlineUser(Integer.valueOf(id));
    }

    /**
     * 消息监听
     * @param message 客户端发来的消息
     * @param id 客户端id
     */
    @OnMessage
    public void OnMessage(String message,@PathParam("id")String id){
        log.info("收到消息"+message);
        webSocket.msgHandler.handleMessage(message,id,webSocketSet.get(id).session);
    }

    /**
     * 向指定客户端发送消息
     * @param id 客户端id
     * @param message 要发送的消息
     */
    public void appointSend(String id,String message){
        try {
            if(webSocketSet.get(id) == null){
                return;
            }
            boolean open = webSocketSet.get(id).session.isOpen();
            if (open){
                webSocketSet.get(id).session.getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void groupSend(long id,String message){
        try {
            for (String idKey : webSocketSet.keySet()){
                if ( Long.valueOf(idKey).longValue() != id){
                    webSocketSet.get(idKey).session.getBasicRemote().sendText(message);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 有人员进入房间时，向房间其他人转发
     */
    public void enterRoom(JSONObject jsonObject){
        roomService.addRoom(jsonObject.getLongValue("sender"),jsonObject.getLongValue("roomId"));
        List<Long> roomId = roomService.findMembersByRoomId(jsonObject.getLongValue("roomId"));
        for (long membersId : roomId){
            if (membersId != jsonObject.getLongValue("sender")){
                appointSend(String.valueOf(membersId),JSON.toJSONString(jsonObject));
            }
        }
    }

    /**
     * 向房间其他人发送IceCandidate消息
     */
    public void sendIceCandidate(JSONObject jsonObject){
        List<Long> members = roomService.findMembersByRoomId(jsonObject.getLongValue("roomId"));
        log.info("sendIceCandidate-----{}",members==null ? "null" : members.size());
        if (members != null && members.size() > 0)
        for (Long membersId : members){
            if (!membersId.equals(jsonObject.getLong("sender"))){
                appointSend(String.valueOf(membersId),JSON.toJSONString(jsonObject));
            }
        }
    }

    /**
     * 向房间其他人发送退出房间消息
     */
    public void handleLeave(JSONObject jsonObject){
        List<Long> sender = roomService.findMembersByRoomId(jsonObject.getLong("roomId"));
        for (Long member : sender){
            if (member != jsonObject.getLong("sender")){
                appointSend(String.valueOf(member),JSON.toJSONString(jsonObject));
            }
        }
    }

    /**
     * 向其他人发送拨号消息
     */
    public void sendCall(JSONObject jsonObject){
        appointSend(jsonObject.getString("receiver"),JSON.toJSONString(jsonObject));
    }

    /**
     * 处理是否接听电话邀请消息
     */
    public void handleAnswerCall(JSONObject jsonObject){
        appointSend(jsonObject.getString("receiver"),JSON.toJSONString(jsonObject));
    }

    /**
     *
     * @param jsonObject
     */
    public void sendGiftMsg(JSONObject jsonObject){
        List<Long> sender = roomService.findMembersByRoomId(jsonObject.getLong("roomId"));
        for (Long member : sender){
            appointSend(String.valueOf(member),JSON.toJSONString(jsonObject));
        }
    }

    /**
     * 处理视频挂断消息
     * @param jsonObject
     */
    public void handleHangUp(JSONObject jsonObject) {
        long roomId = jsonObject.getLongValue("roomId");
        long sender = jsonObject.getLongValue("sender");
        List<Long> membersByRoomId = roomService.findMembersByRoomId(roomId);
        //删除房间
        roomService.deleteRoom(roomId);
        for (long memberId : membersByRoomId){
            if (sender != memberId){//判断挂断者是不是房间创建人
                appointSend(String.valueOf(memberId),JSON.toJSONString(jsonObject));
            }
        }
    }

    /**
     * 将接收的消息发送给房间所有成员
     * @param jsonObject 接收的消息
     */
    public void handleChatMessage(JSONObject jsonObject){
        String roomId = jsonObject.getString("roomId");
        //查询该房间的所有用户ID
        List<Long> membersByRoomId = roomService.findMembersByRoomId(Long.valueOf(roomId));
        for (Long aLong : membersByRoomId) {
            //对所有客户端发消息
            appointSend(String.valueOf(aLong), JSON.toJSONString(jsonObject));
        }
    }
}
